library(ggplot2)
library(tidyverse)
diamonds %>%
count(cut) %>%
ggplot() +
aes(amount = n, r0 = 0, r = 1, fill = cut, x0 = 0, y0 = 0) +
ggforce::stat_pie()
## Warning: Using the `size` aesthetic in this geom was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` in the `default_aes` field and elsewhere instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Here we’re mostly piggybacking on ggforce::StatPie, but we’d like to have more default rather than required aesthetics, an the external circle area to be meaningful; so data$amount
compute_panel_wedge <- function(data, scales, n = 360, sep = 0){
# defaulting aesthetics, instead of requiring
if(!("x0" %in% names(data))){data$x0 <- 0}
if(!("y0" %in% names(data))){data$y0 <- 0}
if(!("r0" %in% names(data))){data$r0 <- 0}
if(!("r" %in% names(data))) {data$r <- sqrt(sum(data$amount)/pi)} # area will be equal to amount
# maybe change 'amount' to 'weight'?
# piggybacking from StatPie
ggforce::StatPie$compute_panel(data, scales = scales, n = n, sep = sep)
}
We define a StatWedge, which is closely related to ggforce::StatPie, but has fewer required aesthetics.
# For reference... showing the abreviated ggforce::StatPie
# StatPie <- ggproto('StatPie', Stat,
# compute_panel = function(data, scales, n = 360, sep = 0) {.......},
# required_aes = c('x0', 'y0', 'r0', 'r', 'amount'),
# default_aes = aes(explode = NULL)
# )
StatWedge <- ggplot2::ggproto(
`_class` = 'StatWedge',
`_inherit` = ggplot2::Stat,
compute_panel = compute_panel_wedge,
required_aes = c('amount'),
default_aes = ggplot2::aes(x0 = NULL, y0 = NULL,
r0 = NULL, r = NULL,
explode = NULL)
)
# Gentle modification from ggforce::GeomArcBar, changing color (was black) and fill (was NA) defaults
GeomArcWedge <- ggplot2::ggproto('GeomArcWedge', ggforce::GeomShape,
default_aes = ggforce:::combine_aes(ggforce::GeomShape$default_aes,
ggplot2::aes(colour = NA, fill = "grey"))
)
Almost same as stat_pie, but using the GeomArcWedge defined above and StatWedge defined above
geom_wedge <- function(mapping = NULL, data = NULL, geom = 'arc_wedge',
position = 'identity', n = 360, sep = 0, na.rm = FALSE,
show.legend = NA, inherit.aes = TRUE, ...) {
layer(
stat = StatWedge, data = data, mapping = mapping, geom = geom,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, n = n, sep = sep, ...)
)
}
library(tidyverse)
diamonds %>%
count(cut) %>%
ggplot() +
aes(amount = n) +
geom_wedge()
last_plot() +
aes(fill = cut)
last_plot() +
aes(alpha = n)
last_plot() +
aes(r0 = .5, r = 1)
last_plot() +
aes(x0 = 5)
last_plot() +
aes(r = n)
diamonds |>
count(cut, clarity) |>
ggplot() +
facet_wrap(~clarity) +
geom_wedge(color = "blue", alpha = .2) +
aes(amount = n, fill = cut)
last_plot() +
aes(r = 1) # back to unit circle...
Titanic %>%
data.frame() %>%
uncount(Freq) ->
tidyTitanic
tidyTitanic %>%
count(Sex, Survived) %>%
ggplot() +
aes(amount = n, fill = Sex) +
geom_wedge()
last_plot() +
facet_wrap(~Sex)
## Bayesian thinking
# Given Female, prob survived
last_plot() +
aes(fill = Survived)
# Given Survived, prob female
last_plot() +
facet_wrap(~Survived) +
aes(fill = Sex)
last_plot() +
aes(explode = c(0,0, 5, 0))
# 2201 little wedges
In fact you get a pie back even without aggregating (something you may notice above…). Ultimately, we’d want to move to some counting in the backgroun. Amount will be like ‘weight’ in geom_bar()/stat_count()
tidyTitanic %>%
ggplot() +
aes(fill = Sex, amount = 1) +
geom_wedge()
last_plot() +
aes(fill = sort(Sex))